package com.yueke.gemini;
import io.jsonwebtoken.Claims;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.filters.RemoteIpFilter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import com.yueke.gemini.exection.RRException;
import com.yueke.gemini.modules.jwt.utils.JwtUtil;
import com.yueke.gemini.utils.XssHttpServletRequestWraper;



/**
 * 自定义Filter
 * @author qxw
 *
 * Spring Boot自动添加了OrderedCharacterEncodingFilter和HiddenHttpMethodFilter，并且我们可以自定义Filter。
 * 实现Filter接口，实现Filter方法
 * 添加@Configurationz 注解，将自定义Filter加入过滤链
 * 
 */

@Configuration
public class WebConfiguration {
	  private static final Logger LOG = LoggerFactory.getLogger(WebConfiguration.class);
	  private static final PathMatcher pathMatcher = new AntPathMatcher();
	    @Bean
	    public RemoteIpFilter remoteIpFilter() {
	        return new RemoteIpFilter();
	    }
	     
	    @SuppressWarnings({ "unchecked", "rawtypes" })
		@Bean
	    public FilterRegistrationBean testFilterRegistration() {
	        FilterRegistrationBean registration = new FilterRegistrationBean();
	        registration.setFilter(new MyFilter());
	        registration.addUrlPatterns("/*");
	        registration.addInitParameter("paramName", "paramValue");
	        registration.setName("MyFilter");
	        registration.setOrder(1);
	        return registration;
	    }
	     
	    public class MyFilter implements Filter {
	    
	        @Override
			public void destroy() {
	        	
	        }
	 
	        @Override
			public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain filterChain)
	                throws IOException, ServletException {
	            HttpServletRequest request = (HttpServletRequest) srequest;
	            HttpServletResponse respone=(HttpServletResponse)sresponse;
	            try {
	                if(isProtectedUrl(request)){
	                	LOG.info("api访问前缀链接开始验证。。。。。。。。。。。。。");
	                    String token = request.getHeader("Authorization");
	                    
	                    //凭证为空
	                    if(StringUtils.isBlank(token)){
	                        throw new RRException("Authorization 不能为空", HttpStatus.UNAUTHORIZED.value());
	                    }
	                    
	                    //检查jwt令牌, 如果令牌不合法或者过期, 里面会直接抛出异常, 下面的catch部分会直接返回
	                    Claims claims = JwtUtil.validateToken(token);
	                    if(claims == null || JwtUtil.isTokenExpired(claims.getExpiration())){
	                        throw new RRException("Authorization 失效，请重新登录", HttpStatus.UNAUTHORIZED.value());
	                    }
	                    
	                    //重新包装request 设置userId
	    	            request = JwtUtil.validateTokenAndAddUserIdToHeader(request);
	                }
	            } catch (Exception e) {
	            	respone.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
	                return;
	            }
	           
	            //如果jwt令牌通过了检测, 那么就把request传递给后面的RESTful api
	            filterChain.doFilter(new XssHttpServletRequestWraper(request),respone);    
	        }
	 
	    
	        @Override
			public void init(FilterConfig arg0) throws ServletException {
	        }
	    }
	    
	    //我们只对地址 /api 开头的api检查jwt. 不然的话登录/login也需要jwt
		private boolean isProtectedUrl(HttpServletRequest request) {
	        return pathMatcher.match("/jwt/api/**", request.getServletPath());
	    }
}
